import Foundation
import UIKit
import ObjectiveC

public class TraceManager {
    /// 单例
    public static let shared = TraceManager()
    
    /// 配置
    public var config = TraceConfig()
    
    /// 用户ID
    public var userId: String?
    
    /// 地理位置
    public var location: Location?
    
    private let storage = TraceStorage()
    private var uploader: TraceUploader?
    
    private var pageViewStartTime: [String: TimeInterval] = [:]
    
    // 添加App运行时长统计相关变量
    private var appActiveStartTime: TimeInterval = 0
    private var appTotalRunningTime: TimeInterval = 0
    private var isAppActive: Bool = false
    private var lastBackgroundTime: TimeInterval = 0
    
    private init() {}
    
    /// 初始化SDK
    public func initialize(config: TraceConfig = TraceConfig()) {
        self.config = config
        
        if config.isEnabled {
            // 加载历史运行时长
            loadRunningTime()
            
            uploader = TraceUploader(storage: storage)
            setupAutoTracking()
        }
    }
    
    /// 设置用户ID
    public func setUserId(_ userId: String?) {
        self.userId = userId
    }
    
    /// 设置地理位置
    public func setLocation(longitude: Double, latitude: Double, country: String? = nil, province: String? = nil, city: String? = nil) {
        self.location = Location(longitude: longitude, latitude: latitude, country: country, province: province, city: city)
    }
    
    /// 清除地理位置
    public func clearLocation() {
        self.location = nil
    }
    
    /// 手动上报事件
    public func track(event: String, payload: [String: Any]? = nil) {
        guard config.isEnabled else { return }
        
        let currentPage = TraceUtils.currentViewController()?.description ?? "Unknown"
        let traceEvent = TraceEvent(event: event, payload: payload, page: currentPage)
        storage.saveEvent(traceEvent)
        
        // 检查是否达到定量上报阈值
        let threshold = config.uploadStrategy.threshold
        if storage.loadEvents().count >= threshold {
            uploader?.uploadEvents()
        }
    }
    
    /// 页面浏览开始
    public func pageViewStart(pageName: String) {
        guard config.isEnabled && config.autoTrackPageView else { return }
        
        pageViewStartTime[pageName] = Date().timeIntervalSince1970
        
        let payload: [String: Any] = ["action": "enter"]
        track(event: "page_view", payload: payload)
    }
    
    /// 页面浏览结束
    public func pageViewEnd(pageName: String) {
        guard config.isEnabled && config.autoTrackPageView else { return }
        
        let endTime = Date().timeIntervalSince1970
        guard let startTime = pageViewStartTime[pageName] else { return }
        
        let duration = Int((endTime - startTime) * 1000)
        pageViewStartTime.removeValue(forKey: pageName)
        
        let payload: [String: Any] = [
            "action": "exit",
            "page_name": pageName,
            "duration": duration
        ]
        
        let traceEvent = TraceEvent(event: "page_view", payload: payload, page: pageName, duration: duration)
        storage.saveEvent(traceEvent)
    }
    
    /// 手动上报崩溃
    public func trackCrash(reason: String, stackTrace: String) {
        guard config.isEnabled else { return }
        
        let payload: [String: Any] = [
            "reason": reason,
            "stack_trace": stackTrace
        ]
        
        track(event: "app_crash", payload: payload)
        uploader?.uploadEvents() // 立即上报崩溃事件
    }
    
    /// 手动触发上报
    public func flush() {
        uploader?.uploadEvents()
    }
    
    // MARK: - Private Methods
    
    private func setupAutoTracking() {
        if config.autoTrackAppLifecycle {
            setupAppLifecycleTracking()
        }
        
        if config.autoTrackCrash {
            setupCrashTracking()
        }
        
        if config.autoTrackClick {
            setupClickTracking()
        }
    }
    
    private func setupAppLifecycleTracking() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(applicationDidBecomeActive),
            name: UIApplication.didBecomeActiveNotification,
            object: nil
        )
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(applicationWillResignActive),
            name: UIApplication.willResignActiveNotification,
            object: nil
        )
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(applicationDidEnterBackground),
            name: UIApplication.didEnterBackgroundNotification,
            object: nil
        )
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(applicationWillTerminate),
            name: UIApplication.willTerminateNotification,
            object: nil
        )
    }
    
    private func setupCrashTracking() {
        NSSetUncaughtExceptionHandler { exception in
            let reason = exception.reason ?? "Unknown"
            let stackTrace = exception.callStackSymbols.joined(separator: "\n")
            TraceManager.shared.trackCrash(reason: reason, stackTrace: stackTrace)
        }
    }
    
    private func setupClickTracking() {
        // 这里需要使用Method Swizzling来实现点击事件的自动采集
        // 由于Method Swizzling的实现比较复杂，这里省略具体实现
        // 实际项目中可以通过替换UIControl的sendAction:to:forEvent:方法来实现
    }
    
    @objc private func applicationDidBecomeActive() {
        // 记录App激活开始时间
        appActiveStartTime = Date().timeIntervalSince1970
        isAppActive = true
        
        track(event: "app_start", payload: ["type": "active"])
    }
    
    @objc private func applicationWillResignActive() {
        // 计算本次活跃时长并累加到总时长
        if isAppActive {
            let currentTime = Date().timeIntervalSince1970
            let sessionDuration = currentTime - appActiveStartTime
            appTotalRunningTime += sessionDuration
            isAppActive = false
        }
        
        track(event: "app_end", payload: [
            "type": "resign",
            "session_duration": Int(Date().timeIntervalSince1970 - appActiveStartTime),
            "total_duration": Int(appTotalRunningTime)
        ])
    }
    
    @objc private func applicationDidEnterBackground() {
        // 记录进入后台的时间
        lastBackgroundTime = Date().timeIntervalSince1970
        
        track(event: "app_background", payload: [
            "total_duration": Int(appTotalRunningTime)
        ])
    }
    
    @objc private func applicationWillTerminate() {
        // 计算最终的运行时长并上报
        let finalDuration = calculateFinalRunningTime()
        
        track(event: "app_terminate", payload: [
            "total_duration": Int(finalDuration)
        ])
        
        // 保存总运行时长到本地，以便下次启动时累加
        saveRunningTime()
        
        flush() // 应用终止前尝试上报所有事件
    }
    
    // 计算最终运行时长
    private func calculateFinalRunningTime() -> TimeInterval {
        var finalDuration = appTotalRunningTime
        
        // 如果App是从活跃状态直接终止的，需要计算最后一段时间
        if isAppActive {
            let currentTime = Date().timeIntervalSince1970
            let lastSessionDuration = currentTime - appActiveStartTime
            finalDuration += lastSessionDuration
        }
        
        return finalDuration
    }
    
    // 保存运行时长到本地存储
    private func saveRunningTime() {
        let finalDuration = calculateFinalRunningTime()
        let previousTotalTime = UserDefaults.standard.double(forKey: "com.vichat.trace.totalRunningTime")
        let newTotalTime = previousTotalTime + finalDuration
        UserDefaults.standard.set(newTotalTime, forKey: "com.vichat.trace.totalRunningTime")
    }
    
    // 加载历史运行时长
    private func loadRunningTime() {
        let previousTotalTime = UserDefaults.standard.double(forKey: "com.vichat.trace.totalRunningTime")
        appTotalRunningTime = previousTotalTime
    }
    
    /// 获取当前会话运行时长（秒）
    public func getCurrentSessionDuration() -> TimeInterval {
        guard isAppActive else { return 0 }
        return Date().timeIntervalSince1970 - appActiveStartTime
    }
    
    /// 获取App总运行时长（秒）
    public func getTotalRunningTime() -> TimeInterval {
        var totalTime = appTotalRunningTime
        
        // 如果App当前是活跃状态，加上当前会话时长
        if isAppActive {
            totalTime += getCurrentSessionDuration()
        }
        
        return totalTime
    }
    
    /// 初始化SDK
    public func initialize(config: TraceConfig = TraceConfig()) {
        self.config = config
        
        if config.isEnabled {
            // 加载历史运行时长
            loadRunningTime()
            
            uploader = TraceUploader(storage: storage)
            setupAutoTracking()
        }
    }
    
    /// 设置用户ID
    public func setUserId(_ userId: String?) {
        self.userId = userId
    }
    
    /// 设置地理位置
    public func setLocation(longitude: Double, latitude: Double, country: String? = nil, province: String? = nil, city: String? = nil) {
        self.location = Location(longitude: longitude, latitude: latitude, country: country, province: province, city: city)
    }
    
    /// 清除地理位置
    public func clearLocation() {
        self.location = nil
    }
    
    /// 手动上报事件
    public func track(event: String, payload: [String: Any]? = nil) {
        guard config.isEnabled else { return }
        
        let currentPage = TraceUtils.currentViewController()?.description ?? "Unknown"
        let traceEvent = TraceEvent(event: event, payload: payload, page: currentPage)
        storage.saveEvent(traceEvent)
        
        // 检查是否达到定量上报阈值
        let threshold = config.uploadStrategy.threshold
        if storage.loadEvents().count >= threshold {
            uploader?.uploadEvents()
        }
    }
    
    /// 页面浏览开始
    public func pageViewStart(pageName: String) {
        guard config.isEnabled && config.autoTrackPageView else { return }
        
        pageViewStartTime[pageName] = Date().timeIntervalSince1970
        
        let payload: [String: Any] = ["action": "enter"]
        track(event: "page_view", payload: payload)
    }
    
    /// 页面浏览结束
    public func pageViewEnd(pageName: String) {
        guard config.isEnabled && config.autoTrackPageView else { return }
        
        let endTime = Date().timeIntervalSince1970
        guard let startTime = pageViewStartTime[pageName] else { return }
        
        let duration = Int((endTime - startTime) * 1000)
        pageViewStartTime.removeValue(forKey: pageName)
        
        let payload: [String: Any] = [
            "action": "exit",
            "page_name": pageName,
            "duration": duration
        ]
        
        let traceEvent = TraceEvent(event: "page_view", payload: payload, page: pageName, duration: duration)
        storage.saveEvent(traceEvent)
    }
    
    /// 手动上报崩溃
    public func trackCrash(reason: String, stackTrace: String) {
        guard config.isEnabled else { return }
        
        let payload: [String: Any] = [
            "reason": reason,
            "stack_trace": stackTrace
        ]
        
        track(event: "app_crash", payload: payload)
        uploader?.uploadEvents() // 立即上报崩溃事件
    }
    
    /// 手动触发上报
    public func flush() {
        uploader?.uploadEvents()
    }
    
    // MARK: - Private Methods
    
    private func setupAutoTracking() {
        if config.autoTrackAppLifecycle {
            setupAppLifecycleTracking()
        }
        
        if config.autoTrackCrash {
            setupCrashTracking()
        }
        
        if config.autoTrackClick {
            setupClickTracking()
        }
    }
    
    private func setupAppLifecycleTracking() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(applicationDidBecomeActive),
            name: UIApplication.didBecomeActiveNotification,
            object: nil
        )
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(applicationWillResignActive),
            name: UIApplication.willResignActiveNotification,
            object: nil
        )
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(applicationDidEnterBackground),
            name: UIApplication.didEnterBackgroundNotification,
            object: nil
        )
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(applicationWillTerminate),
            name: UIApplication.willTerminateNotification,
            object: nil
        )
    }
    
    private func setupCrashTracking() {
        NSSetUncaughtExceptionHandler { exception in
            let reason = exception.reason ?? "Unknown"
            let stackTrace = exception.callStackSymbols.joined(separator: "\n")
            TraceManager.shared.trackCrash(reason: reason, stackTrace: stackTrace)
        }
    }
    
    private func setupClickTracking() {
        // 这里需要使用Method Swizzling来实现点击事件的自动采集
        // 由于Method Swizzling的实现比较复杂，这里省略具体实现
        // 实际项目中可以通过替换UIControl的sendAction:to:forEvent:方法来实现
    }
    
    @objc private func applicationDidBecomeActive() {
        track(event: "app_start", payload: ["type": "active"])
    }
    
    @objc private func applicationWillResignActive() {
        // 计算本次活跃时长并累加到总时长
        if isAppActive {
            let currentTime = Date().timeIntervalSince1970
            let sessionDuration = currentTime - appActiveStartTime
            appTotalRunningTime += sessionDuration
            isAppActive = false
            
            // 更新详细使用时长统计
            AppUsageTracker.shared.updateUsageTime(sessionDuration)
        }
        
        track(event: "app_end", payload: [
            "type": "resign",
            "session_duration": Int(Date().timeIntervalSince1970 - appActiveStartTime),
            "total_duration": Int(appTotalRunningTime),
            "today_duration": Int(AppUsageTracker.shared.getTodayUsageTime()),
            "weekly_duration": Int(AppUsageTracker.shared.getWeeklyUsageTime()),
            "monthly_duration": Int(AppUsageTracker.shared.getMonthlyUsageTime())
        ])
    }
    
    @objc private func applicationDidEnterBackground() {
        track(event: "app_background")
    }
    
    @objc private func applicationWillTerminate() {
        track(event: "app_terminate")
        flush() // 应用终止前尝试上报所有事件
    }
}

// MARK: - UIViewController扩展，用于自动跟踪页面浏览
extension UIViewController {
    private static let swizzleViewDidAppear: Void = {
        let originalSelector = #selector(UIViewController.viewDidAppear(_:))
        let swizzledSelector = #selector(UIViewController.trace_viewDidAppear(_:))
        
        guard let originalMethod = class_getInstanceMethod(UIViewController.self, originalSelector),
              let swizzledMethod = class_getInstanceMethod(UIViewController.self, swizzledSelector) else {
            return
        }
        
        method_exchangeImplementations(originalMethod, swizzledMethod)
    }()
    
    private static let swizzleViewDidDisappear: Void = {
        let originalSelector = #selector(UIViewController.viewDidDisappear(_:))
        let swizzledSelector = #selector(UIViewController.trace_viewDidDisappear(_:))
        
        guard let originalMethod = class_getInstanceMethod(UIViewController.self, originalSelector),
              let swizzledMethod = class_getInstanceMethod(UIViewController.self, swizzledSelector) else {
            return
        }
        
        method_exchangeImplementations(originalMethod, swizzledMethod)
    }()
    
    public static func setupPageViewTracking() {
        swizzleViewDidAppear
        swizzleViewDidDisappear
    }
    
    @objc private func trace_viewDidAppear(_ animated: Bool) {
        trace_viewDidAppear(animated)
        
        if TraceManager.shared.config.autoTrackPageView {
            let pageName = String(describing: type(of: self))
            TraceManager.shared.pageViewStart(pageName: pageName)
        }
    }
    
    @objc private func trace_viewDidDisappear(_ animated: Bool) {
        trace_viewDidDisappear(animated)
        
        if TraceManager.shared.config.autoTrackPageView {
            let pageName = String(describing: type(of: self))
            TraceManager.shared.pageViewEnd(pageName: pageName)
        }
    }
}